package com.lcq.demo.service;

import com.lcq.demo.common.converter.ProductDTOConverter;
import com.lcq.demo.common.converter.ProductPOConverter;
import com.lcq.demo.common.entity.PageResult;
import com.lcq.demo.entity.dto.ProductDTO;
import com.lcq.demo.entity.po.Product;
import com.lcq.demo.repository.ProductRepository;
import com.lcq.demo.repository.ProductTypeRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import java.util.stream.Collectors;

/**
 * @author 240701005
 */
@Service
@Slf4j
public class ProductService {

    @Resource
    private ProductRepository repository;

    @Resource
    private ProductTypeRepository productTypeRepository;

    /**
     * 根据主键查询
     */
    public ProductDTO getById(Long id) {
        Product product = repository.getById(id);
        return ProductPOConverter.INSTANCE.convertPoToDto(product);
    }

    /**
     * 插入数据
     */
    public Boolean insert(ProductDTO productDTO) {
        productDTO.setIsDeleted(0);
        productDTO.setCreateTime(new Date(System.currentTimeMillis()));
        Product product = ProductDTOConverter.INSTANCE.convertToPo(productDTO);
        repository.save(product);
        return true;
    }

    /**
     * 更新数据
     */
    public Boolean update(ProductDTO productDTO) {
        productDTO.setUpdateTime(new Date(System.currentTimeMillis()));
        Product product = ProductDTOConverter.INSTANCE.convertToPo(productDTO);
        repository.save(product);
        return true;
    }

    /**
     * 删除数据
     */
    public Boolean deleteById(Long id) {
        try {
            repository.deleteById(id);
            return true;
        } catch (Exception e) {
            log.error("ProductService.deleteById.error:{}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 条件查询
     */
    public PageResult<ProductDTO> getProducts(ProductDTO productDTO) {
        PageResult<ProductDTO> pageResult = new PageResult<>();
        Specification<Product> specification = (Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
            List<Predicate> predicates = new ArrayList<>();

            if (productDTO.getId() != null) {
                predicates.add(cb.equal(root.get("id"), productDTO.getId()));
            }
            if (productDTO.getProductName() != null && !productDTO.getProductName().isEmpty()) {
                predicates.add(cb.equal(root.get("productName"), productDTO.getProductName()));
            }
            if (productDTO.getProductType() != null && !productDTO.getProductType().isEmpty()) {
                predicates.add(cb.equal(root.get("productType"), productDTO.getProductType()));
            }
            return cb.and(predicates.toArray(new Predicate[0]));
        };
        long count = repository.count(specification);
        Pageable pageable = PageRequest.of(productDTO.getPageNum() - 1, productDTO.getPageSize());
        Page<Product> pageRes = repository.findAll(specification, pageable);
        List<ProductDTO> productDTOList = pageRes.getContent().stream()
                .map(ProductPOConverter.INSTANCE::convertPoToDto)
                .collect(Collectors.toList());
        setProductName4DtoList(productDTOList);
        pageResult.setResult(productDTOList);
        pageResult.setPageSize(productDTO.getPageSize());
        pageResult.setPageNo(productDTO.getPageNum());
        pageResult.setTotal((int) count);
        return pageResult;
    }

    public void setProductName4DtoList(List<ProductDTO> productDTOList) {
        for (ProductDTO productDTO : productDTOList) {
            productDTO.setProductTypeName(productTypeRepository.getById(Long.valueOf(productDTO.getProductType())).getTypeName());
        }
    }
}
